package com.ruoyi.business.task;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.common.enums.UserTagEnum;
import com.ruoyi.common.utils.Func;
import com.ruoyi.common.utils.ObjectUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;

@Slf4j
@RestController
@RequestMapping("/retry/v2/")
@AllArgsConstructor
public class AppUsetTagInitTask {

    private IAppUserService userService;

    private IRealNameAuthService realNameAuthService;

    private IRealNameAuthLogService realNameAuthLogService;

    private ICreditAccountService creditAccountService;

    private ICreditApplyService creditApplyService;

    private ILoanOrderService loanOrderService;

    private IIncreasedLimitLogService increasedLimitLogService;

    private IAppUserMarkService appUserMarkService;

    private ICustomerInfoService customerInfoService;

    private ICustBankCardService custBankCardService;

    private IBankAccountService bankAccountService;


    @PostMapping("runTask")
    public void runTask() {

        int coreSize = 4;
        int threadExcSize = 1000;
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(coreSize, coreSize, 0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>());

        List<AppUser> userAll = userService.list(new QueryWrapper<AppUser>().select("user_uuid", "password", "phone"));

        int size = (userAll.size() / threadExcSize) + 1;
        List<List<AppUser>> lists = ObjectUtil.averageAssign(userAll, size);
        Semaphore semaphore = new Semaphore(coreSize);
        //每条线程每次处理约500个用户
        for (List<AppUser> userList : lists) {

            try {
                semaphore.acquire();
                threadPoolExecutor.execute(new UserTagTask(userList, semaphore));
            } catch (InterruptedException e) {
                log.error("thread执行异常", e);
            }
        }

        //初始化安装未注册标签
        List<String> phoneList = userService.selectUnRegisterUserList();
        try {
            List<AppUserMark> appUserMarkList = new ArrayList<>();
            phoneList.forEach(e -> {
                appUserMarkList.add(AppUserMark.builder().registerPhone(e)
                        .firstTag(UserTagEnum.UN_REGISTERED.getFirstTag())
                                .createTime(new Date()).updateTime(new Date())
                        .build());
            });

            appUserMarkService.insertBatch(appUserMarkList);
        } catch (Exception e) {
            log.error("Run 安装未注册标签 异常", e);
        } finally {
            semaphore.release();
        }
        threadPoolExecutor.shutdown();

    }

    private class UserTagTask implements Runnable {

        private List<AppUser> userList;

        private Semaphore semaphore;

        UserTagTask(List<AppUser> userList, Semaphore semaphore) {
            this.userList = userList;
            this.semaphore = semaphore;
        }

        @Override
        public void run() {

            try {
                List<AppUserMark> appUserMarkList = new ArrayList<>();
                userList.forEach(e -> {
                    appUserMarkList.add(new UserDetail(e).getUserTagEnum());
                });

                appUserMarkService.insertBatch(appUserMarkList);
                //添加 &rewriteBatchedStatements=true
                // pool-3-thread-2执行时间为：3649
                // pool-3-thread-1执行时间为：7219

                //不添加
                //pool-3-thread-2执行时间为：8878
                //pool-3-thread-1执行时间为：10494
            } catch (Exception e) {
                log.error("Run异常", e);
            } finally {
                semaphore.release();
            }

        }

    }


    private class UserDetail {

        private AppUser user;

        private RealNameAuth realNameAuth;

        private CreditAccount creditAccount;

        private CustomerInfo customerInfo;

        UserDetail(AppUser appUser) {
            this.user = appUser;
        }

        public AppUserMark getUserTagEnum() {
            UserTagEnum tagEnum = getTagEnum();
            AppUserMark appUserMark = AppUserMark.builder().userId(user.getUserUuid()).build();
            appUserMark.setFirstTag(tagEnum.getFirstTag());
            appUserMark.setSecondTag(tagEnum.getSecondTag());
            appUserMark.setRegisterPhone(user.getPhone());
            if (Func.isNotEmpty(customerInfo)) {
                appUserMark.setCustNo(customerInfo.getCustNo());
            }
            if (tagEnum.getFirstTag().equals("Identity verification failed")) {
                appUserMark.setRemark(tagEnum.getSecondTag());
            }
            if (Func.isNotEmpty(realNameAuth)) {
                appUserMark.setLastName(realNameAuth.getLastName());
                appUserMark.setBvnPhone(realNameAuth.getPhoneNumber());
                appUserMark.setBirthday(realNameAuth.getBirthDate());
                appUserMark.setGender(realNameAuth.getGender());
            }
            if (Func.isNotEmpty(creditAccount)) {
                appUserMark.setCreditLine(creditAccount.getCreditLine());
                appUserMark.setLoanQuota(creditAccount.getLoanQuota());
                IncreasedLimitLog increasedAmt = increasedLimitLogService.getIncreasedAmtByCust(creditAccount.getCustNo());
//                BigDecimal bg = increasedLimitLogService.getIncreasedAmtByCust(creditAccount.getCustNo());
                appUserMark.setIncreasedAmt(increasedAmt.getIncreasedAmt());
            }
            Date date = new Date();
            appUserMark.setCreateTime(date);
            appUserMark.setUpdateTime(date);
            return appUserMark;
        }

        private UserTagEnum getTagEnum() {
            RealNameAuth realNameAuth = realNameAuthService.getOne(new QueryWrapper<RealNameAuth>().eq("user_id", user.getUserUuid()));
            //注册 无密码
            customerInfo = customerInfoService.getOne(new QueryWrapper<CustomerInfo>().eq("user_id", user.getUserUuid()));
            if (Func.isEmpty(user.getPassword()) && Func.isEmpty(realNameAuth)) {
                return UserTagEnum.REGISTERED_NOT_PASSWORD;
            }
            //未实名 -> 注册 有密码
            if (Func.isEmpty(realNameAuth)) {
                //是否实名失败
                QueryWrapper<RealNameAuthLog> logQueryWrapper = new QueryWrapper<RealNameAuthLog>().eq("user_id", user.getUserUuid()).last("order by id desc limit 1");
                RealNameAuthLog realNameAuthLog = realNameAuthLogService.getOne(logQueryWrapper);
                //如果没有实名 -> 注册 有密码
                if (Func.isEmpty(realNameAuthLog)) {
                    return UserTagEnum.REGISTERED_NOT_VERIFIED;
                }
                UserTagEnum userTagEnum = UserTagEnum.exceptionMapper(realNameAuthLog.getErrorMsg());
                return Optional.ofNullable(userTagEnum).orElse(UserTagEnum.getDiy("Identity verification failed",realNameAuthLog.getErrorMsg()));
            }
            this.realNameAuth = realNameAuth;

            //是否授信
            CreditApply creditApply = creditApplyService.getOne(new QueryWrapper<CreditApply>().eq("cust_no", realNameAuth.getCustNo()).last("order by id desc limit 1"));
            if (Func.isEmpty(creditApply)) {
                //没有授信 -> 实名成功
                return UserTagEnum.IDENTITY_VERIFIED_SUCCESS;
            }
            //没有授信 -> 授信失败
            if (1 != creditApply.getApplyStatus()) {
                //risk被拒
                if (0 == creditApply.getApplyStatus()) {
                    return UserTagEnum.CREDIT_APPLICATION_FAILED_RISK_REJECT;
                } else {
                    //系统原因
                    return UserTagEnum.CREDIT_APPLICATION_FAILED;
                }
            }
            this.creditAccount =  creditAccountService.getOne(new QueryWrapper<CreditAccount>().eq("cust_no", realNameAuth.getCustNo()));

            LoanOrder loanOrder = loanOrderService.getOne(new QueryWrapper<LoanOrder>().eq("cust_no", realNameAuth.getCustNo()).last("order by id desc limit 1"));
            if (Func.isEmpty(loanOrder)) {
                //没有提现记录 -> 授信成功 有无Account
                if (bankAccountService.countByCustNo(realNameAuth.getUserId()) > 0) {
                    return UserTagEnum.CREDIT_APPLICATION_SUCCESS_ACCOUNT_EXISTED;
                } else {
                    return UserTagEnum.CREDIT_APPLICATION_SUCCESS_ACCOUNT_NOT_EXIST;
                }
            }

            if (0 == loanOrder.getLoanStatus()) {
                return UserTagEnum.LOAN_REJECT;
            }

            if (10 == loanOrder.getLoanStatus()) {
                return UserTagEnum.LOAN_FAILED_WITHDRAWAL_CANCEL;
            }

            if (4 == loanOrder.getLoanStatus()) {
                int cardCount = custBankCardService.count(new QueryWrapper<CustBankCard>().eq("cust_no", loanOrder.getCustNo()));
                return cardCount > 0 ? UserTagEnum.LOAN_SUCCEED_BIND_CARD : UserTagEnum.LOAN_SUCCEED_NOT_CARD;
            }
            return UserTagEnum.LOAN_FAILED;
        }

    }


}
